#pragma once
#include <pthread.h>
#include <functional>
#include "Socket.hpp"

using func_t = std::function<std::string(std::string &, bool *error_code)>;

class TcpServer;

class ThreadData
{
public:
    ThreadData(TcpServer *tsr, Net_Work::Socket *newsock)
        : _tsr(tsr), _newsock(newsock)
    {
    }

public:
    Net_Work::Socket *_newsock;
    TcpServer *_tsr;
};

class TcpServer
{
public:
    TcpServer(uint16_t localport, func_t handler_request)
        : _port(localport), _listensock(new Net_Work::TcpSocket()), _handler_request(handler_request)
    {
        _listensock->BuildListenSocketMethod(_port, Net_Work::defaultbacklog);
    }

    void Loop()
    {
        while (true)
        {
            std::string peerip;
            uint16_t peerport;
            Net_Work::Socket *newsock = _listensock->AcceptConnection(&peerip, &peerport);
            if (newsock == nullptr)
                continue;

           std::cout << "获取一个新连接, sockfd: " << newsock->GetSockfd() << " client info: " << peerip << ":" << peerport << std::endl;
            pthread_t _tid;
            ThreadData *td = new ThreadData(this, newsock);
            pthread_create(&_tid,nullptr,ThreadRun,td);
        }
    }

    static void* ThreadRun(void * args)
    {
        pthread_detach(pthread_self());
        ThreadData *td=static_cast<ThreadData *>(args);

        std::string inbufferstream;
        while(true)
        {
            bool ok=true;
            if(!td->_newsock->Recv(&inbufferstream,1024))
                break;
            //处理
            std::string send_string =td->_tsr->_handler_request(inbufferstream,&ok);
            if(ok)
            {
                if(!send_string.empty())
                {
                    td->_newsock->Send(send_string);
                }
                else
                {
                    std::cout<<"Send Error"<<std::endl;
                    break;
                }
            }
        }
        td->_newsock->CloseSockfd();
        delete td->_newsock;
        delete td;
        return nullptr;    
        
    }

    ~TcpServer()
    {
        delete _listensock;
    }

private:
    int _port;
    Net_Work::Socket *_listensock;

public:
    func_t _handler_request;
};